package com.neusoft.bizcore.webauth.secret.jwt;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import com.neusoft.bizcore.auth.common.jwt.JwtAuthProvider;
import com.neusoft.bizcore.webauth.secret.userpass.UserPassAuthenticationToken;

public class JwtAuthTokenFilter extends OncePerRequestFilter {

    public static final String HEADER_STRING = "Authentication";

    private final JwtAuthProvider jwtAuthProvider;

    public JwtAuthTokenFilter(final JwtAuthProvider jwtAuthProvider) {
        this.jwtAuthProvider = jwtAuthProvider;
    }

    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
            final FilterChain filterChain)
            throws ServletException, IOException {
        final String token = request.getHeader(JwtAuthTokenFilter.HEADER_STRING);
        if ((null != token) && this.jwtAuthProvider.validate(token)) {
            final String username = this.jwtAuthProvider.parseUsername(token);
            if ((username != null) && (SecurityContextHolder.getContext().getAuthentication() == null)) {

                final List<String> roles = this.jwtAuthProvider.parseRoles(token);
                final Collection<? extends GrantedAuthority> authorities = roles.stream()
                        .map(role -> new SimpleGrantedAuthority(role)).collect(Collectors.toSet());
                final User user = new User(username, "", authorities);
                final UserPassAuthenticationToken authentication = new UserPassAuthenticationToken(
                        user, null, authorities);
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(
                        request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }

        filterChain.doFilter(request, response);

    }

}
